#include <jni.h>
#include <string>
#include <android/log.h>

extern "C" {
//#include "include/libavformat/avformat.h"
//#include "include/libavcodec/avcodec.h"
//#include "include/libavutil/avutil.h"
}

#define OPEN_LOG 1

#define LOGE(...) \
if(OPEN_LOG){__android_log_print(ANDROID_LOG_ERROR,"lingtao",__VA_ARGS__);}
#define J4A_ALOGE(...) \
if(OPEN_LOG2){__android_log_print(ANDROID_LOG_ERROR,"J4A_ALOGE",__VA_ARGS__);}

#define LOGEU(tag,...) \
if(OPEN_LOG){__android_log_print(ANDROID_LOG_ERROR,tag,__VA_ARGS__);}

#define USE_H264BSF 0

extern "C" JNIEXPORT jstring JNICALL
Java_com_lingtao_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    char info[10000] = {0};
//    sprintf(info, "%s\n", avcodec_configuration());
    return env->NewStringUTF(info);
}

#define RECORD1
#ifdef RECORD

int startRecored(const char *out_filename) {

    AVOutputFormat *ofmt = NULL;
    //Input AVFormatContext and Output AVFormatContext
    AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
    AVPacket pkt;
    const char *in_filename;
    int ret, i, count = 0;
    int videoindex = -1;
    int audeoindex = -1;

    int videoindex_out = -1;//视频输出流的下标
    int audioindex_out = -1;//音频输出流的下标

    int frame_index = 0;
    in_filename = "http://ips.ifeng.com/video19.ifeng.com/video09/2014/06/16/1989823-102-086-0009.mp4";
    in_filename = "E:/applications/Visual Studio/Project/SDl2Demo/SDL2Demo/music.mp4";
    in_filename = "E:/applications/Visual Studio/Project/SDl2Demo/SDL2Demo/weixinmp4.mp4";
    in_filename = "rtmp://58.200.131.2:1935/livetv/hunantv";
    in_filename = "E:/applications/Visual Studio/Project/SDl2Demo/SDL2Demo/崇拜.mp4";
    in_filename = "E:/applications/Visual Studio/Project/SDl2Demo/SDL2Demo/女儿情.mp4";
    in_filename = "http://ips.ifeng.com/video19.ifeng.com/video09/2014/06/16/1989823-102-086-0009.mp4";
//    in_filename = "rtmp://58.200.131.2:1935/livetv/hunantv";
//    in_filename = "rtsp://183.6.152.75:5222/live/72@3B9ACA17";

//    out_filename = "E:/applications/Visual Studio/Project/SDl2Demo/SDL2Demo/out_file/临时存储.mp4";


    av_register_all();
    //Network
    avformat_network_init();
    printf("开始读取\n");
    //Input

//    AVDictionary* opts = NULL;
//    av_dict_set(&opts, "rtsp_transport", "tcp",0); //设置tcp
//    av_dict_set(&opts, "rtsp_transport", "udp",0); //设置udp
//    av_dict_set(&opts, "stimeout", "10000000", 0);//设置超时5秒


    if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
        printf("Could not open input file.\n");
        goto end;
    }
    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
        printf("Failed to retrieve input stream information");
        goto end;
    }
    printf("流的个数=%d\n", ifmt_ctx->nb_streams);
    for (i = 0; i < ifmt_ctx->nb_streams; i++) {
        AVStream *av_stream = ifmt_ctx->streams[i];
        AVMediaType mediaType = av_stream->codecpar->codec_type;

        if (mediaType == AVMEDIA_TYPE_VIDEO) {
            videoindex = i;
            printf("视频流= %d\n", i);//1

        } else if (mediaType == AVMEDIA_TYPE_AUDIO) {
            audeoindex = i;
            printf("音频流= %d\n", i);//2
        } else {
            continue;
        }
    }

    printf("-----------------start----------------------\n");
    av_dump_format(ifmt_ctx, 0, in_filename, 0);
    printf("-----------------end----------------------\n");

    //Output
    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);

    if (!ofmt_ctx) {
        printf("Could not create output context\n");
        ret = AVERROR_UNKNOWN;
        goto end;
    }
    ofmt = ofmt_ctx->oformat;
    for (i = 0; i < ifmt_ctx->nb_streams; i++) {
        if (i == videoindex || i == audeoindex) {
            AVStream *in_stream = ifmt_ctx->streams[i];
            AVCodecParameters *codecpar = in_stream->codecpar;
            AVMediaType mediaType = codecpar->codec_type;

            AVCodec *dec = avcodec_find_decoder(codecpar->codec_id);
            AVStream *out_stream = avformat_new_stream(ofmt_ctx,
                                                       reinterpret_cast<const AVCodecID *>(dec));
            if (!out_stream) {
                printf("Failed allocating output stream\n");
                ret = AVERROR_UNKNOWN;
                goto end;
            }
            if (i == videoindex) {
                videoindex_out = out_stream->index;
            } else if (i == audeoindex) {
                audioindex_out = out_stream->index;
            } else {


            }
            codecpar->codec_tag = 0;
            AVCodecContext *context = avcodec_alloc_context3(dec);
            ret = avcodec_parameters_to_context(context, codecpar);
            //ret = avcodec_parameters_from_context(codecpar, context);
            //out_stream->codecpar = codecpar;
            out_stream->codec = context;

        } else {
            continue;
        }
    }
    printf("videoindex_out=%d\n", videoindex_out);//0
    printf("audioindex_out=%d\n", audioindex_out);//1


    //Dump Format------------------
    av_dump_format(ofmt_ctx, 0, out_filename, 1);
    //Open output URL
    if (!(ofmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
        if (ret < 0) {
            printf("Could not open output URL '%s'", out_filename);
            goto end;
        }
    }
    //Write file header
    ret = avformat_write_header(ofmt_ctx, NULL);
    if (ret < 0) {
        printf("Error occurred when opening output URL\n");
        goto end;
    }

#if USE_H264BSF
    AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
#endif
    while (1) {
        AVStream *in_stream, *out_stream;
        //Get an AVPacket
        ret = av_read_frame(ifmt_ctx, &pkt);

        if (ret < 0) {
            break;
        }

        printf("pkt.pts =%lld, pkt.dts=%lld\n", pkt.pts, pkt.dts);

        int pkt_index = pkt.stream_index;

        //1 2
        if (pkt.stream_index == videoindex || pkt.stream_index == audeoindex) {
            in_stream = ifmt_ctx->streams[pkt.stream_index];

            if (pkt.stream_index == videoindex) {
                out_stream = ofmt_ctx->streams[videoindex_out];
            } else {
                out_stream = ofmt_ctx->streams[audioindex_out];
            }
            pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base,
                                       (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
            pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base,
                                       (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
            pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
            pkt.pos = -1;
            //printf("pts=%lld,dts=%lld,duration=%lld\n", pkt.pts, pkt.dts, pkt.duration);
            //Print to Screen
            if (pkt.stream_index == videoindex) {
                frame_index++;
                count++;
                if (frame_index % 1000 == 0) {
                    printf("Receive %d video frames from input URL\n", frame_index);

                }
            }
            //ret = av_write_frame(ofmt_ctx, &pkt);
            //printf("输出流的数量：%d\n", ofmt_ctx->nb_streams);
            //printf("当前包的流下标：%d\n", pkt.stream_index);
            ret = av_interleaved_write_frame(ofmt_ctx, &pkt);

            if (ret < 0) {

                break;
            }
            if (count > 2000) {
                break;
            }

        }
        av_free_packet(&pkt);

    }

#if USE_H264BSF
    av_bitstream_filter_close(h264bsfc);
#endif

    //Write file trailer
    av_write_trailer(ofmt_ctx);
    end:
    avformat_close_input(&ifmt_ctx);
    /* close output */
    if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
        avio_close(ofmt_ctx->pb);
    avformat_free_context(ofmt_ctx);
    if (ret < 0 && ret != AVERROR_EOF) {
        printf("Error occurred.\n");
        return -1;
    }
    return 0;
}

#endif

extern "C"
JNIEXPORT void JNICALL
Java_com_lingtao_myapplication_MainActivity_recordVideo(JNIEnv *env, jobject thiz, jstring path) {
    env->GetStringChars(path, 0);
    const char *out_filename = env->GetStringUTFChars(path, 0);
//    char str[25];
//    sprintf(str, "%d", avcodec_version());
//    __android_log_print(ANDROID_LOG_ERROR,"lingtao",__VA_ARGS__);
//    LOGE("%s",str)
//    startRecored(out_filename);
}